package com.example.certificate.aspect;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.example.certificate.annoatiton.LoginToken;
import com.example.certificate.annoatiton.PassToken;
import com.example.certificate.config.SpringContextBean;
import com.example.certificate.entity.User;
import com.example.certificate.utils.RedisTemplateUtil;
import com.example.certificate.utils.ResultConstant;
import com.example.certificate.utils.ResultEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;

public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    /*
     * 预先处理
     *
     * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        String token = request.getHeader("Authorization");
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //检查是否有passToken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(LoginToken.class)) {
            LoginToken userLoginToken = method.getAnnotation(LoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (StringUtils.isEmpty(token)) {
                    sendJsonMessage(response, new ResultEntity(ResultConstant.ACCESS_DENIED.getResultCode(), "token不能为空"));
                    return false;
                }
                // 获取 token 中的 user
                if (redisTemplateUtil==null){
                    redisTemplateUtil = SpringContextBean.getBean(RedisTemplateUtil.class);
                }

                String userInfo = (String) redisTemplateUtil.getVal(token);
                if (StringUtils.isEmpty(userInfo)){
                    sendJsonMessage(response, new ResultEntity(ResultConstant.ACCESS_DENIED.getResultCode(), "该用户不存在"));
                    return false;
                }
                User user = JSONObject.parseObject(userInfo,User.class);
                user.setToken(token);
                if (user.getStatus() == 0){
                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
                    sendJsonMessage(response,new ResultEntity(ResultConstant.ACCESS_DENIED.resultCode, "该用户已被禁用，请联系管理员"));
                }
                request.setAttribute("CurrentUser", user);
            }
        }

        return true;
    }


    public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {
        response.setContentType("application/json; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue,  /*序列化写入映射值*/
                SerializerFeature.WriteDateUseDateFormat)); /*序列化写入日期使用日期格式*/
        writer.close(); /*关闭流，清除缓冲*/
        response.flushBuffer();
    }
    /*
     * 后期处理
     * */

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }

    /*
     * 完成后
     * */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }
}
